package org.pentaho.cubic.client.solution;

import java.util.ArrayList;

import org.pentaho.cubic.client.dialogs.NotificationDialog;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.XMLParser;


public class SolutionManager {
	private ArrayList<ISolutionDocumentListener> listeners = new ArrayList<ISolutionDocumentListener>();
	
	private Document solutionDocument;
	private static SolutionManager instance;

	private static boolean fetching = false;

	private SolutionManager() {
		flagSolutionDocumentLoaded(false);
	}

	private native void flagSolutionDocumentLoaded(boolean docLoaded)
	/*-{
	    $wnd.mantle_repository_loaded = docLoaded;
	  }-*/;

	public static SolutionManager getInstance() {
		if (instance == null) {
			instance = new SolutionManager();
		}
		return instance;
	}

	public void addSolutionDocumentListener(ISolutionDocumentListener listener) {
		listeners.add(listener);
		synchronized (SolutionManager.class) {
			if (!fetching && solutionDocument != null) {
				listener.beforeFetchSolutionDocument();
				listener.onFetchSolutionDocument(solutionDocument);
			}
		}
	}

	public void removeSolutionDocumentListener(ISolutionDocumentListener listener) {
		listeners.remove(listener);
	}

	private void fireSolutionDocumentFetched() {
		fetching = false;
		for (ISolutionDocumentListener listener : listeners) {
			listener.onFetchSolutionDocument(solutionDocument);
		}
		// flag that we have the document so that other things might start to use it (PDB-500)
		flagSolutionDocumentLoaded(true);
	}

	public void beforeFetchSolutionDocument() {
		for (ISolutionDocumentListener listener : listeners) {
			listener.beforeFetchSolutionDocument();
		}
	}

	public void fetchSolutionDocument(final boolean forceReload) {
		if (forceReload || solutionDocument == null) {
			fetchSolutionDocument(null);
		}
	}

	public void fetchSolutionDocument(final AsyncCallback<Document> callback, final boolean forceReload) {
		if (forceReload || solutionDocument == null) {
			fetchSolutionDocument(callback);
		} else {
			callback.onSuccess(solutionDocument);
		}
	}

	public void fetchSolutionDocument(final AsyncCallback<Document> callback) {
		//WaitPopup.getInstance().setVisible(true);
		// notify listeners that we are about to talk to the server (in case there's anything they want to do
		// such as busy cursor or tree loading indicators)
		beforeFetchSolutionDocument();

		RequestBuilder builder = null;
		if (GWT.isScript()) {
			String path = Window.Location.getPath();
			if (path.contains("/cubic"))
				path = path.replace("/cubic", "");
			if (!path.endsWith("/")) { //$NON-NLS-1$
				path = path.substring(0, path.lastIndexOf("/") + 1); //$NON-NLS-1$
			}
			builder = new RequestBuilder(RequestBuilder.GET, path + "SolutionRepositoryService?component=getSolutionRepositoryDoc"); //$NON-NLS-1$
		} else {
			builder = new RequestBuilder(RequestBuilder.GET,
			"/MantleService?passthru=SolutionRepositoryService&component=getSolutionRepositoryDoc&userid=joe&password=password"); //$NON-NLS-1$
		}

		RequestCallback internalCallback = new RequestCallback() {

			public void onError(Request request, Throwable exception) {
				//WaitPopup.getInstance().setVisible(false);
				NotificationDialog dlx = new NotificationDialog("Solution Document", "couldNotGetRepositoryDocument");
				dlx.center();
			}

			public void onResponseReceived(Request request, Response response) {
				// ok, we have a repository document, we can build the GUI
				// consider caching the document
				solutionDocument = (Document) XMLParser.parse((String) (String) response.getText());
				fireSolutionDocumentFetched();
				if (callback != null) {
					callback.onSuccess(solutionDocument);
				}
				//WaitPopup.getInstance().setVisible(false);
			}

		};
		try {
			builder.sendRequest(null, internalCallback);
		} catch (RequestException e) {
			//WaitPopup.getInstance().setVisible(false);
			NotificationDialog dlx = new NotificationDialog("Solution Document", "couldNotGetRepositoryDocument");
			dlx.center();
		}

	}


}
